﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OxyPlot;

namespace AutoCorrelatorGUI.Model
{
   public class Well_Analysis
   {
      public int ZeroCrossings { get; set; }

      private double[] _PeakValArr = new double[5];
      private double[] _PeakHzArr = new double[5];

      public double Peak0Val { get { return _PeakValArr[0]; } set { _PeakValArr[0] = value; } }
      public double Peak1Val { get { return _PeakValArr[1]; } set { _PeakValArr[1] = value; } }
      public double Peak1Hz { get { return _PeakHzArr[1]; } set { _PeakHzArr[1] = value; } }
      public double Peak2Val { get { return _PeakValArr[2]; } set { _PeakValArr[2] = value; } }
      public double Peak2Hz { get { return _PeakHzArr[2]; } set { _PeakHzArr[2] = value; } }
      public double Peak3Val { get { return _PeakValArr[3]; } set { _PeakValArr[3] = value; } }
      public double Peak3Hz { get { return _PeakHzArr[3]; } set { _PeakHzArr[3] = value; } }
      public double Peak4Val { get { return _PeakValArr[4]; } set { _PeakValArr[4] = value; } }
      public double Peak4Hz { get { return _PeakHzArr[4]; } set { _PeakHzArr[4] = value; } }

      private double[] _TroughsValArr = new double[5];
      private double[] _TroughsHzArr = new double[5];

      public double Trough1Val { get { return _TroughsValArr[1]; } set { _TroughsValArr[1] = value; } }
      public double Trough1Hz { get { return _TroughsHzArr[1]; } set { _TroughsHzArr[1] = value; } }
      public double Trough2Val { get { return _TroughsValArr[2]; } set { _TroughsValArr[2] = value; } }
      public double Trough2Hz { get { return _TroughsHzArr[2]; } set { _TroughsHzArr[2] = value; } }
      public double Trough3Val { get { return _TroughsValArr[3]; } set { _TroughsValArr[3] = value; } }
      public double Trough3Hz { get { return _TroughsHzArr[3]; } set { _TroughsHzArr[3] = value; } }
      public double Trough4Val { get { return _TroughsValArr[4]; } set { _TroughsValArr[4] = value; } }
      public double Trough4Hz { get { return _TroughsHzArr[4]; } set { _TroughsHzArr[4] = value; } }

      internal void GetPeakTroughArr(out double[] peakVal, out double[] peakHz, out double[] troughVal, out double[] troughHz)
      {
         peakVal = _PeakValArr;
         peakHz = _PeakHzArr;
         troughVal = _TroughsValArr;
         troughHz = _TroughsHzArr;
      }

      internal void Calc(Well_Output output, double _IntervalTimeMS)
      {
         IList<DataPoint> values = output.Data;

         ZeroCrossings = 0;

         for (int i = 0; i < 5; i++)
         {
            _PeakValArr[i] = 0.0;
            _PeakHzArr[i] = 0.0;
            _TroughsValArr[i] = 0.0;
            _TroughsHzArr[i] = 0.0;
         }

         //First find the maximum value 
         int MaxIdx = 0;
         Peak0Val = Double.NegativeInfinity;

         //Even number means we need to find the peak and set that 0 to 0
         for (int i = 0; i < values.Count; i++)
         {
            if (values[i].Y > Peak0Val)
            {
               Peak0Val = values[i].Y;
               MaxIdx = i;
            }
         }

         double prevVal = Peak0Val;
         double prevDeriv = 0.0;

         int peakIdx = 1;
         int troughIdx = 1;

         double sliceInSec = Properties.Settings.Default.IntervalTimeMS / 1000.0;

         //Now moving forwards, we check for changes in the derivative and for Zero crossings
         for (int i = MaxIdx + 1; i < values.Count; i++)
         {
            //Check for zero crossing
            if (prevVal * values[i].Y < 0.0)
            {
               ZeroCrossings += 2;
            }
            else if (prevVal * values[i].Y == 0.0 && prevVal != 0.0)
            {
               ZeroCrossings += 2;
            }

            //Calc the current derivative
            double currDeriv = values[i].Y - prevVal;

            if (peakIdx < 5 && currDeriv * prevDeriv < 0.0)
            {
               //Either a peak or a trough
               if (currDeriv > 0.0)
               {
                  //Trough
                  _TroughsValArr[troughIdx] = prevVal;
                  _TroughsHzArr[troughIdx] = 1.0 / (2.0 * (i - 1 - MaxIdx) * sliceInSec);
                  troughIdx++;
               }
               else
               {
                  //Peak
                  _PeakValArr[peakIdx] = prevVal;
                  _PeakHzArr[peakIdx] = 1.0 / (2.0 * (i - 1 - MaxIdx) * sliceInSec);
                  peakIdx++;
               }
            }

            prevDeriv = currDeriv;
            prevVal = values[i].Y;
         }
      }
   }
}
